#include <config.h>
#include <debug.h>
#include <header.h>
#include <rules.h>
#include <xml_util.h>

#include "gui.h"
#include "language.h"
static GtkListStore *list_store;
static GtkTreeSelection *selection = NULL;
enum
{
  DESCRIPTION,
  PROTOCOL,
  LOCALPORT,
  REMOTEPORT,
  ACTION,
  STATUS
};
static GtkWidget *get_tree_view(GtkListStore *list_store);
static GtkListStore *get_list_store(void);
static void cellrender_toggled(GtkCellRendererToggle *cell_renderer,
                               gchar *path,
                               gpointer user_data);
static void init_rules_list_store(GtkListStore *list_store);
static void delete_item(GtkWidget *widget, gpointer data);
static void convert_port_from_string_to_int(char *port, int *from, int *to);
GtkWidget *get_custom_page(void)
{
  GtkWidget *vbox = NULL;
  GtkWidget *hbox_top = NULL;
  GtkWidget *hbox_bottom = NULL;
  GtkWidget *scrolled_window = NULL;
  GtkWidget *scrolled_window_vbox = NULL;
  GtkWidget *del_button = NULL;
  GtkWidget *add_button = NULL;
  GtkWidget *tree_view = NULL;
  vbox = gtk_vbox_new(FALSE, 0);
  hbox_top = gtk_hbox_new(TRUE, 0);
  hbox_bottom = gtk_hbox_new(TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), hbox_top, FALSE, FALSE, 5);
  gtk_box_pack_start(GTK_BOX(vbox), hbox_bottom, FALSE, FALSE, 10);
  scrolled_window = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC,
                                 GTK_POLICY_AUTOMATIC);
  gtk_widget_set_usize(scrolled_window, SCROLLED_WINDOW_WIDTH,
                       SCROLLED_WINDOW_HEIGHT);
  gtk_box_pack_start(GTK_BOX(hbox_top), GTK_WIDGET(scrolled_window), TRUE, TRUE, 0);
  scrolled_window_vbox = gtk_vbox_new(FALSE, 0);
  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
                                        scrolled_window_vbox);
  list_store = get_list_store();
  tree_view = get_tree_view(list_store);
  init_rules_list_store(list_store);
  gtk_box_pack_start(GTK_BOX(scrolled_window_vbox), tree_view, TRUE, TRUE, 0);

  add_button = gtk_button_new_from_stock(GTK_STOCK_ADD);
  gtk_box_pack_start(GTK_BOX(hbox_bottom), GTK_WIDGET(add_button), FALSE, FALSE, 0);

  del_button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
  gtk_box_pack_start(GTK_BOX(hbox_bottom), GTK_WIDGET(del_button), FALSE, FALSE, 0);


  /*connect signal*/
  gtk_signal_connect(GTK_OBJECT(del_button), "clicked",
                     G_CALLBACK(delete_item), NULL);
  gtk_signal_connect(GTK_OBJECT(add_button), "clicked",
                     G_CALLBACK(show_add_rule_dialog), NULL);
  return vbox;
}
void add_user_defined_list_store(char *desc, int action, int proto,
                                 int lpf, int lpt,
                                 int rpf, int rpt)
{
  GtkTreeIter iter;
  char caction[8] = {0};
  char cproto[5] = {0};
  char localport[15] = {0};
  char remoteport[15] = {0};

  if (NF_ACCEPT == action)
  {
    sprintf(caction, TEXT_ACTION_ACCEPT);
  }
  else if (NF_DROP == action)
  {
    sprintf(caction, TEXT_ACTION_DROP);
  }
  if (IPPROTO_TCP == proto)
  {
    sprintf(cproto, TEXT_PROTO_TCP);
  }
  else if (IPPROTO_UDP == proto)
  {
    sprintf(cproto, TEXT_PROTO_UDP);
  }

  if (lpf == lpt)
  {
    if (0 == lpf)
    {
      sprintf(localport, TEXT_ANYPORT);
    }
    else
    {
      sprintf(localport, "%d", lpf);
    }
  }
  else
  {
    sprintf(localport, "%d-%d", lpf, lpt);
  }

  if (rpf == rpt)
  {
    if (0 == rpf)
    {
      sprintf(remoteport, "anyport");
    }
    else
    {
      sprintf(remoteport, "%d", rpf);
    }
  }
  else
  {
    sprintf(remoteport, "%d-%d", rpf, rpt);
  }

  gtk_list_store_append(list_store, &iter);
  gtk_list_store_set(list_store, &iter,
                     DESCRIPTION, desc,
                     PROTOCOL, cproto,
                     LOCALPORT, localport,
                     REMOTEPORT, remoteport,
                     ACTION, caction,
                     STATUS, TRUE,
                     -1);
}
static GtkListStore *get_list_store(void)
{
  GtkListStore *list_store = NULL;
  list_store = gtk_list_store_new(6,
                                  G_TYPE_STRING,/*description*/
                                  G_TYPE_STRING,/*protocol*/
                                  G_TYPE_STRING,/*localport*/
                                  G_TYPE_STRING,/*remoteport*/
                                  G_TYPE_STRING,/*action*/
                                  G_TYPE_BOOLEAN);/*status*/
  return list_store;
}
static GtkWidget *get_tree_view(GtkListStore *list_store)
{
  GtkWidget *tree_view = NULL;
  GtkTreeViewColumn *column = NULL;
  GtkCellRenderer *cell_renderer = NULL;

  tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store));
  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
  /*description*/
  column = gtk_tree_view_column_new();
  gtk_tree_view_column_set_title(column, TEXT_COLUMN_DESC);
  gtk_tree_view_column_set_resizable(column, TRUE);
  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
  cell_renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
  gtk_tree_view_column_set_attributes(column, cell_renderer, "text", DESCRIPTION, NULL);

  /*protocol*/
  column = gtk_tree_view_column_new();
  gtk_tree_view_column_set_title(column, TEXT_COLUMN_PROTO);
  gtk_tree_view_column_set_resizable(column, TRUE);
  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
  cell_renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
  gtk_tree_view_column_set_attributes(column, cell_renderer, "text", PROTOCOL, NULL);

  /*local port*/
  column = gtk_tree_view_column_new();
  gtk_tree_view_column_set_title(column, TEXT_COLUMN_LOCAL_PORT);
  gtk_tree_view_column_set_resizable(column, TRUE);
  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
  cell_renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
  gtk_tree_view_column_set_attributes(column, cell_renderer, "text", LOCALPORT, NULL);

  /*remote port*/
  column = gtk_tree_view_column_new();
  gtk_tree_view_column_set_title(column, TEXT_COLUMN_REMOTE_PORT);
  gtk_tree_view_column_set_resizable(column, TRUE);
  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
  cell_renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
  gtk_tree_view_column_set_attributes(column, cell_renderer, "text", REMOTEPORT, NULL);

  /*action*/
  column = gtk_tree_view_column_new();
  gtk_tree_view_column_set_title(column, TEXT_COLUMN_POLICY);
  gtk_tree_view_column_set_resizable(column, TRUE);
  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
  cell_renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
  gtk_tree_view_column_set_attributes(column, cell_renderer, "text", ACTION, NULL);

  /*status*/
  column = gtk_tree_view_column_new();
  gtk_tree_view_column_set_title(column, TEXT_COLUMN_STATUS);
  gtk_tree_view_column_set_resizable(column, TRUE);
  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
  cell_renderer = gtk_cell_renderer_toggle_new();
  gtk_tree_view_column_pack_start(column, cell_renderer, TRUE);
  gtk_tree_view_column_set_attributes(column, cell_renderer, "active", STATUS, NULL);
  gtk_signal_connect(GTK_OBJECT(cell_renderer), "toggled",
                     GTK_SIGNAL_FUNC(cellrender_toggled), NULL);

  return tree_view;
}

static void delete_item(GtkWidget *widget, gpointer data)
{
  GtkTreeIter iter;
  char *desc = NULL;
  char *localport = NULL;
  char *remoteport = NULL;
  char *proto = NULL;
  char *action = NULL;
  int protocol = 0;
  int lpf = 0;
  int lpt = 0;
  int rpf = 0;
  int rpt = 0;
  int act = 0;
  GtkTreeModel *model = GTK_TREE_MODEL(list_store);
  gtk_tree_selection_get_selected(selection, &model, &iter);
  gtk_tree_model_get(GTK_TREE_MODEL(list_store), &iter, DESCRIPTION, &desc,
                     LOCALPORT, &localport, REMOTEPORT, &remoteport,
                     PROTOCOL, &proto, ACTION, &action, -1);
  convert_port_from_string_to_int(localport, &lpf, &lpt);
  convert_port_from_string_to_int(remoteport, &rpf, &rpt);
  protocol = strcmp(proto, TEXT_PROTO_TCP) == 0 ? IPPROTO_TCP : IPPROTO_UDP;
  act = strcmp(action, TEXT_ACTION_ACCEPT) == 0 ? NF_ACCEPT : NF_DROP;
  /*delete rules*/
  delete_user_defined_rules(protocol, lpf, lpt, rpf, rpt, act);
  /*delete xml entry*/
  xml_delete_user_defined_rules((xmlChar *)desc);
  /*delete list store*/
  gtk_list_store_remove(list_store, &iter);
  if (desc != NULL)
  {
    free(desc);
  }
  if (localport != NULL)
  {
    free(localport);
  }
  if (remoteport != NULL)
  {
    free(remoteport);
  }
  if (proto != NULL)
  {
    free(proto);
  }
  if (action != NULL)
  {
    free(action);
  }
}
static void cellrender_toggled(GtkCellRendererToggle *cell_renderer,
                               gchar *path,
                               gpointer user_data)
{
  GtkTreeIter iter;
  gboolean status = 0;
  GValue value;
  char *desc = NULL;
  char *localport = NULL;
  char *remoteport = NULL;
  char *proto = NULL;
  char *action = NULL;
  int protocol = 0;
  int lpf = 0;
  int lpt = 0;
  int rpf = 0;
  int rpt = 0;
  int act = 0;
  gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(list_store), &iter, path);
  gtk_tree_model_get(GTK_TREE_MODEL(list_store), &iter, DESCRIPTION, &desc,
                     LOCALPORT, &localport, REMOTEPORT, &remoteport,
                     PROTOCOL, &proto, ACTION, &action, STATUS, &status,
                     -1);
  convert_port_from_string_to_int(localport, &lpf, &lpt);
  convert_port_from_string_to_int(remoteport, &rpf, &rpt);
  protocol = strcmp(proto, TEXT_PROTO_TCP) == 0 ? IPPROTO_TCP : IPPROTO_UDP;
  act = strcmp(action, TEXT_ACTION_ACCEPT) == 0 ? NF_ACCEPT : NF_DROP;

  value.g_type = G_TYPE_BOOLEAN;
  if (0 == status)
  {
    /*select the checkbutton*/
    value.data[0].v_int = 1;
    gtk_list_store_set_value(list_store, &iter, STATUS, &value);
    /*modiy xml entry*/
    xml_set_user_defined_rules_status((xmlChar *)desc, (xmlChar *)YES_VALUE);
    /*add rules*/
    add_user_defined_rules(protocol, lpf, lpt, rpf, rpt, act);
  }
  else
  {
    value.data[0].v_int = 0;
    gtk_list_store_set_value(list_store, &iter, STATUS, &value);
    /*modiy xml entry*/
    xml_set_user_defined_rules_status((xmlChar *)desc, (xmlChar *)NO_VALUE);
    /*delete rules*/
    delete_user_defined_rules(protocol, lpf, lpt, rpf, rpt, act);
  }
  if (desc != NULL)
  {
    free(desc);
  }
}
static void init_rules_list_store(GtkListStore *list_store)
{
}
static void convert_port_from_string_to_int(char *port, int *from, int *to)
{
  char * mark = NULL;
  mark = strchr(port, '-');
  if (NULL == mark)
  {
    if (0 == strcmp(port, TEXT_ANYPORT))
    {
      *from = *to = 0;
      return;
    }
    *from = *to = atoi(port);
  }
  else
  {
    *from = atoi(port);
    *to = atoi(++mark);
  }
  return;
}
